﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;

namespace SSRS_Plus
{
    public partial class frmServerObjects : Form
    {
        public frmServerObjects()
        {
            InitializeComponent();
        }

        private void frmServerObjects_Load(object sender, EventArgs e)
        {
            LoadData();
        }

        /// <summary>
        /// Populates form controls on form load
        /// </summary>
        private void LoadData()
        {
            lblServer.Text = "Connected to " + ReportWrapper.ActiveServer.ServerName;

            lstvSnapshot.Columns.Add("History ID");
            lstvSnapshot.Columns.Add("Creation Date");
            lstvSnapshot.Columns.Add("Size");

            lstvSnapshot.Columns[0].Width = 200;
            lstvSnapshot.Columns[1].Width = 200;
            lstvSnapshot.Columns[2].Width = 80;

            lstParameter.Columns.Add("Parameter");
            lstParameter.Columns.Add("Value");
            lstParameter.Columns.Add("Type");

            lstParameter.Columns[0].Width = 150;
            lstParameter.Columns[1].Width = 150;
            lstParameter.Columns[2].Width = 150;

            FillReports();
            FillExtensionList();
        }

        /// <summary>
        /// Populates the export format drop-down list with the formats supported by the connected Report Server
        /// </summary>
        private void FillExtensionList()
        {
            lstFormat.Items.Clear();

            foreach (string str in ReportWrapper.GetSupportedExtensions())
            {
                lstFormat.Items.Add(str);
            }

            if (lstFormat.Items.Count > 0)
                lstFormat.SelectedIndex = 0;
        }

        /// <summary>
        /// Populates the tree view with the Report Server contents 
        /// </summary>
        private void FillReports()
        {
            try
            {
                lstServerObjects.Nodes.Clear();

                foreach (Microsoft.SqlServer.ReportExecution.CatalogItem ct in ReportWrapper.GetServerObjects())
                {
                    if (lstServerObjects.Nodes.Find(ct.Path.Replace(@"/" + ct.Name, ""), true).Count() > 0)
                    {
                        lstServerObjects.Nodes.Find(ct.Path.Replace(@"/" + ct.Name, ""), true)[0].Nodes.Add(ct.Path, ct.Name);

                        lstServerObjects.Nodes.Find(ct.Path, true)[0].Tag = ct.Path;
                        lstServerObjects.Nodes.Find(ct.Path, true)[0].ToolTipText = ct.Type.ToString();
                        
                        if (ct.Type == Microsoft.SqlServer.ReportExecution.ItemTypeEnum.DataSource)
                            lstServerObjects.Nodes.Find(ct.Path, true)[0].ImageIndex = 1;
                        else if (ct.Type == Microsoft.SqlServer.ReportExecution.ItemTypeEnum.Folder)
                            lstServerObjects.Nodes.Find(ct.Path, true)[0].ImageIndex = 2;
                        else if (ct.Type == Microsoft.SqlServer.ReportExecution.ItemTypeEnum.Report || ct.Type == Microsoft.SqlServer.ReportExecution.ItemTypeEnum.LinkedReport)
                            lstServerObjects.Nodes.Find(ct.Path, true)[0].ImageIndex = 3;
                    }
                    else
                    {
                        TreeNode tr1 = lstServerObjects.Nodes.Add(ct.Path, ct.Name);
                        tr1.Tag = ct.Path;
                        tr1.ToolTipText = ct.Type.ToString();
                        tr1.ImageIndex = 2;                        
                    }
                }
            }
            catch { }
        }

        /// <summary>
        /// Enable/disable controls that are not applicable to the current selected item
        /// </summary>
        private void ChangeContentState()
        {
            if (lstServerObjects.SelectedNode != null)
            {
                if (lstServerObjects.SelectedNode.ToolTipText.ToString() == "Report" || lstServerObjects.SelectedNode.ToolTipText.ToString() == "LinkedReport")
                {
                    Microsoft.SqlServer.ReportExecution.Property[] p = ReportWrapper.GetReportExecutionSettings(lstServerObjects.SelectedNode.Tag.ToString());

                    // Disable snapshot update button if report is not set to be rendered from a snapshot
                    if ((p[0].Value == "Live" || p[1].Value == "False") && btnUpdateSnap.Enabled)
                    {
                        btnUpdateSnap.Enabled = false;
                    }
                    else if (p[0].Value == "Snapshot" && p[1].Value == "True" && !btnUpdateSnap.Enabled)
                    {
                        btnUpdateSnap.Enabled = true;
                    }
                }
            }
        }        

        private void lstServerObjects_AfterSelect(object sender, TreeViewEventArgs e)
        {
            lstServerObjects.SelectedImageIndex = e.Node.ImageIndex;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="trNode"></param>
        /// <param name="path"></param>
        private void SaveReportsRecursive(TreeNode trNode, string path)
        {
            if (trNode.Checked && trNode.ToolTipText == Microsoft.SqlServer.ReportExecution.ItemTypeEnum.Report.ToString())
            {
                byte[] results = ReportWrapper.DownloadItem(trNode.Tag.ToString());
                FileStream stream = File.Create(path + "\\" + trNode.Text + ".RDL", results.Length);
                stream.Write(results, 0, results.Length);
                stream.Close();
            }

            foreach (TreeNode tn in trNode.Nodes)
            {
                SaveReportsRecursive(tn, path);
            }
        }

        private void btnDownload_Click(object sender, EventArgs e)
        {
            try
            {
                FolderBrowserDialog folder = new FolderBrowserDialog();
                if (folder.ShowDialog() == DialogResult.OK)
                {
                    foreach (TreeNode tn in lstServerObjects.Nodes)
                    {
                        SaveReportsRecursive(tn, folder.SelectedPath);
                    }

                    MessageBox.Show("Item(s) downloaded sucessfully!", "Download", MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        /// <summary>
        /// Populates Subscriptions tab page with the specified reports subscriptions
        /// </summary>
        /// <param name="Item">Fully qualified name of a snapshot enabled report</param>
        private void GetItemDetails(string Item)
        {
            try
            {
                this.Cursor = System.Windows.Forms.Cursors.WaitCursor;

                txtDetails.Text = "";
                txtDetails.Text = ReportWrapper.GetItemDetails(Item).ToString();

                if (lstServerObjects.SelectedNode.ToolTipText.ToString() == "Report" || lstServerObjects.SelectedNode.ToolTipText.ToString() == "LinkedReport")
                {
                    // BUG FIX: Came across a bug where selecting (via double click or enter) any item(s) multiple times will add
                    // more columns to the Subscription view. Disposing of columns (if any) before addition solves the problem.
                    gvSubscription.Columns.Clear();

                    gvSubscription.DataSource = ReportWrapper.GetSubscriptionForReport(Item);

                    gvSubscription.Columns[3].Width = 60;
                    gvSubscription.Columns[0].Visible = false;
                    gvSubscription.Columns[4].Visible = false;
                    gvSubscription.Columns[5].Visible = false;
                    gvSubscription.Columns[6].Visible = false;

                    DataGridViewLinkColumn lc1 = new DataGridViewLinkColumn();
                    lc1.DataPropertyName = "Subscription";
                    lc1.Width = 100;
                    lc1.Name = "Subscription";
                    lc1.HeaderText = "Subscription";
                    gvSubscription.Columns.Add(lc1);

                    DataGridViewLinkColumn lc = new DataGridViewLinkColumn();
                    lc.DataPropertyName = "Action";
                    lc.Width = 75;
                    lc.Name = "Action";
                    lc.HeaderText = "Action";
                    lc.Text = "Re-run";
                    gvSubscription.Columns.Add(lc);


                    gvSubscription.CellContentClick += new DataGridViewCellEventHandler(gvSubscription_CellContentClick);

                    FillSnapshotHistory(Item);
                }

                this.Cursor = System.Windows.Forms.Cursors.Arrow;
            }
            catch 
            {
                this.Cursor = System.Windows.Forms.Cursors.Arrow;
            };
        }

        void gvSubscription_CellContentClick(object sender, DataGridViewCellEventArgs e)
        {
            try
            {
                if (e.ColumnIndex == 8)
                {
                    if (MessageBox.Show("Are you sure want to re-run this subscription?", "Re-run Subscription", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2) == DialogResult.Yes)
                    {
                        this.Cursor = System.Windows.Forms.Cursors.WaitCursor;
                        if (gvSubscription.Columns[e.ColumnIndex] is DataGridViewLinkColumn)
                        {
                            ReportWrapper.RunSubscription(gvSubscription[6, e.RowIndex].Value.ToString(), gvSubscription[4, e.RowIndex].Value.ToString());
                        }
                    }
                }
                else if (e.ColumnIndex == 7)
                {
                    this.Cursor = System.Windows.Forms.Cursors.WaitCursor;
                    lstParameter.Items.Clear();

                    int i = 0;

                    foreach (DataRow dr in ReportWrapper.GetSubscriptionParameter(gvSubscription[4, e.RowIndex].Value.ToString(), gvSubscription[3, e.RowIndex].Value.ToString()).Rows)
                    {
                        ListViewItem itm = new ListViewItem(dr[0].ToString());
                        itm.SubItems.Add(dr[1].ToString());
                        itm.SubItems.Add(dr[2].ToString());

                        if (i % 2 == 0)
                            itm.BackColor = Color.WhiteSmoke;

                        i++;

                        lstParameter.Items.Add(itm);
                    }
                }
                this.Cursor = System.Windows.Forms.Cursors.Arrow;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                this.Cursor = System.Windows.Forms.Cursors.Arrow;
            }
        }

        /// <summary>
        /// Populates snapshots tab page with the specified reports snapshot history
        /// </summary>
        /// <param name="Item">Fully qualified name of a snapshot enabled report</param>
        private void FillSnapshotHistory(string Item)
        {
            try
            {
                lstvSnapshot.Items.Clear();
                ListViewItem lstItem;
                int i = 1;
                foreach (DataRow dr in ReportWrapper.GetSnapshotForReport(Item).Rows)
                {
                    lstItem = new ListViewItem(dr[0].ToString());
                    lstItem.SubItems.Add(dr[1].ToString());
                    lstItem.SubItems.Add(Decimal.Round((Convert.ToDecimal(dr[2]) / 1024.0M)).ToString() + " KB");

                    if (i % 2 != 0)
                        lstItem.BackColor = Color.WhiteSmoke;
                    else
                        lstItem.BackColor = Color.Transparent;

                    lstvSnapshot.Items.Add(lstItem);
                    i++;
                }
            }

            catch { }
        }

        private void lstServerObjects_DoubleClick(object sender, EventArgs e)
        {
            ChangeContentState();

            if (lstServerObjects.SelectedNode != null)
            {
                GetItemDetails(lstServerObjects.SelectedNode.Tag.ToString());
            }
        }

        private void btnExport_Click(object sender, EventArgs e)
        {

            if (lstFormat.Text != "")
            {
                FolderBrowserDialog folder = new FolderBrowserDialog();

                try
                {
                    if (folder.ShowDialog() == DialogResult.OK)
                    {
                        this.Cursor = System.Windows.Forms.Cursors.WaitCursor;

                        foreach (ListViewItem li in lstvSnapshot.Items)
                        {
                            if (li.Checked)
                            {
                                Microsoft.Reporting.WinForms.ReportViewer rv = new Microsoft.Reporting.WinForms.ReportViewer();
                                rv.ProcessingMode = Microsoft.Reporting.WinForms.ProcessingMode.Remote;
                                rv.ServerReport.ReportServerUrl = new Uri(ReportWrapper.ActiveServer.ServerURL.ToString().Replace("/ReportService2005.asmx", ""));
                                rv.ServerReport.ReportPath = lstServerObjects.SelectedNode.Tag.ToString();
                                rv.ServerReport.HistoryId = li.SubItems[0].Text;

                                Microsoft.Reporting.WinForms.Warning[] warnings;
                                string[] streamids;
                                string mimeType;
                                string encoding;
                                string extension;
                                // Not used
                                //string deviceInfo = "";
                                //deviceInfo = "<DeviceInfo><SimplePageHeaders>True</SimplePageHeaders></DeviceInfo>";

                                byte[] bytes = rv.ServerReport.Render(lstFormat.Text, null, out mimeType, out encoding, out extension, out streamids, out warnings);

                                FileStream fs = new FileStream(folder.SelectedPath + "\\" + li.SubItems[0].Text.Replace(":", ""), FileMode.Create);
                                //FileStream fs = new FileStream(sv.FileName, FileMode.Create);

                                fs.Write(bytes, 0, bytes.Length);
                                fs.Close();

                                //if (checkBox1.Checked)
                                //{
                                //    rs1.DeleteReportHistorySnapshot(li.SubItems[1].Text, li.SubItems[0].Text);
                                //}
                            }
                        }

                        MessageBox.Show("Snapshot(s) were exported to " + folder.SelectedPath, "Success", MessageBoxButtons.OK, MessageBoxIcon.Information);
                    }

                    this.Cursor = System.Windows.Forms.Cursors.Arrow;


                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    this.Cursor = System.Windows.Forms.Cursors.Arrow;
                }
            }
            else
            {
                MessageBox.Show("Please select export format!", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
            }
        }

        private void btnDelete_Click(object sender, EventArgs e)
        {
            try
            {
                if (MessageBox.Show("Are you sure you want to delete Snapshot(s) from server?", "Delete...", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2) == DialogResult.Yes)
                {
                    this.Cursor = System.Windows.Forms.Cursors.WaitCursor;

                    foreach (ListViewItem li in lstvSnapshot.Items)
                    {
                        if (li.Checked)
                        {
                            ReportWrapper.DeleteSnapshot(lstServerObjects.SelectedNode.Tag.ToString(), li.SubItems[0].Text);
                        }
                    }

                    MessageBox.Show("Snapshot(s) were deleted successfully from server!", "Success", MessageBoxButtons.OK, MessageBoxIcon.Information);
                    this.Cursor = System.Windows.Forms.Cursors.Arrow;
                }
            }

            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                this.Cursor = System.Windows.Forms.Cursors.Arrow;
            }

        }

        private void btnUpdateSnap_Click(object sender, EventArgs e)
        {
            try
            {
                this.Cursor = System.Windows.Forms.Cursors.WaitCursor;

                String notSnapCompatible = null;

                // TODO Would like to maintain a sorted list of all selected nodes, irrespective of tree structure.
                TreeNode selectedNode = lstServerObjects.SelectedNode;
                while (selectedNode != null)
                {
                    if (selectedNode.ToolTipText == "Report")
                    {
                        String name = selectedNode.Tag.ToString();
                        Microsoft.SqlServer.ReportExecution.Property[] p = ReportWrapper.GetReportExecutionSettings(name);

                        if (p[0].Value == "Snapshot" && p[1].Value == "True") // Report is snapshot enabled
                            ReportWrapper.UpdateSnapshot(name);
                        else
                            notSnapCompatible = notSnapCompatible + name + "\n"; // Get names to inform user they were not updated
                    }

                    selectedNode = selectedNode.NextNode;
                }
                
                // Assuming the new snapshot has been created, update the snapshot list too
                FillSnapshotHistory(lstServerObjects.SelectedNode.Tag.ToString());

                if (notSnapCompatible != null)
                    MessageBox.Show("Some Report snapshots have been updated but the following are not snapshot enabled and were not updated: \n" + notSnapCompatible, "Information", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                else
                    MessageBox.Show("Report snapshots have been updated.", "Success", MessageBoxButtons.OK, MessageBoxIcon.Information);

                this.Cursor = System.Windows.Forms.Cursors.Arrow;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                this.Cursor = System.Windows.Forms.Cursors.Arrow;
            }
        }

        private void lstServerObjects_KeyPress(object sender, KeyPressEventArgs e)
        {
            ChangeContentState();

            if (lstServerObjects.SelectedNode != null && e.KeyChar == 13 /* Enter key */)
            {
                GetItemDetails(lstServerObjects.SelectedNode.Tag.ToString());
            }
        }

        private void tabControl1_Selecting(object sender, TabControlCancelEventArgs e)
        {
            ChangeContentState();
        }
    }
}
